<?php
namespace Icsoc\DataBundle\Model;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Class WebCallModel
 * @package Icsoc\DataBundle\Model
 */
class WebCallModel extends BaseModel
{

    /** @var \Symfony\Component\DependencyInjection\Container */
    public $container;

    /** @var \Doctrine\DBAL\Connection */
    private $dbal;


    /**
     * @param ContainerInterface $container
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
        $this->dbal = $this->container->get('doctrine.dbal.default_connection');
    }

    /**
     * webcall呼入通话记录
     * @param array $param
     * @return array|string
     */
    public function webCall400(array $param = array())
    {
        $vcc_code = empty($param['vcc_code']) ? 0 : $param['vcc_code'];
        $start_time = empty($param['start_time']) ? 0 : $param['start_time'];
        $end_time = empty($param['end_time']) ? '' : $param['end_time'];

        //vcc_code 验证
        $msg = $vcc_id = $this->container->get('icsoc_data.validator')->checkVccCode($vcc_code);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }

        //开始时间
        $msg = $this->container->get('icsoc_data.helper')->isDateTime('开始时间格式不正确', $start_time, 403);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }

        if (!empty($end_time)) {
            $msg = $this->container->get('icsoc_data.helper')->isDateTime('结束时间格式不正确', $end_time, 404);
            if (!empty($msg) && is_array($msg)) {
                return $msg;
            }
            $where = ' AND  w.start_time <= :end_time ';
            $par_arr = array(
                'vcc_id' => $vcc_id,
                'start_time' => strtotime($start_time),
                'end_time' => strtotime($end_time),
            );
        } else {
            $where = '';
            $par_arr = array(
                'vcc_id' => $vcc_id,
                'start_time' => strtotime($start_time),
            );
        }
        $result = $this->dbal->fetchAll(
            'SELECT w.call_id,w.caller,w.called,w.ivr_digits,w.result,w.start_time,w.conn_time,
             w.end_time,w.all_secs,r.record_file '.
            'FROM win_incdr as w LEFT JOIN win_agcdr as r ON w.call_id=r.call_id AND w.vcc_id=r.vcc_id '.
            'WHERE w.vcc_id=:vcc_id AND w.start_time>=:start_time '.$where.' LIMIT 3000',
            $par_arr
        );
        $data = $temp = array();
        if (!empty($result)) {
            foreach ($result as $v) {
                $temp['caller'] = $v['caller'];
                $temp['called'] = $v['called'];
                $temp['call_id'] = $v['call_id'];
                $temp['ivr_digits'] = $v['ivr_digits'];
                $temp['in'] = 'in';
                $temp['start_time'] = empty($v['start_time']) ? '' : date('Y-m-d H:i:s', $v['start_time']);
                $temp['conn_time'] =  empty($v['conn_time']) ? '' : date('Y-m-d H:i:s', $v['conn_time']);
                $temp['end_time'] = empty($v['end_time']) ? '' : date('Y-m-d H:i:s', $v['end_time']);
                $temp['all_secs'] = $v['all_secs'];
                $temp['record_file'] = $v['record_file'];
                $temp['result'] = $v['result']==0 ? '接通' : '未接通';
                $data[] = $temp;
            }
        }
        $ret = array(
            'code' => 200,
            'message' => 'ok',
            'data' => $data,
        );
        return $ret;
    }

    /**
     * 800回呼记录
     * @param array $param
     * @return array|string
     */
    public function webCall800(array $param = array())
    {
        $vcc_code = empty($param['vcc_code']) ? 0 : $param['vcc_code'];
        $start_time = empty($param['start_time']) ? 0 : $param['start_time'];
        $end_time = empty($param['end_time']) ? '' : $param['end_time'];

        //vcc_code 验证
        $msg = $vcc_id = $this->container->get('icsoc_data.validator')->checkVccCode($vcc_code);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }
        //开始时间
        $msg = $this->container->get('icsoc_data.helper')->isDateTime('开始时间格式不正确', $start_time, 403);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }

        if (!empty($end_time)) {
            $msg = $this->container->get('icsoc_data.helper')->isDateTime('结束时间格式不正确', $end_time, 404);
            if (!empty($msg) && is_array($msg)) {
                return $msg;
            }
            $where = ' AND  w.start_time <= :end_time ';
            $par_arr = array(
                'vcc_id' => $vcc_id,
                'start_time' => strtotime($start_time),
                'end_time' => strtotime($end_time),
            );
        } else {
            $where = '';
            $par_arr = array(
                'vcc_id' => $vcc_id,
                'start_time' => strtotime($start_time),
            );
        }

        $result = $this->dbal->fetchAll(
            'SELECT w.caller,w.called,w.result,w.start_time,w.conn_time,w.call_id,
             w.end_time,w.all_sec '.
            ' FROM ac_cdr as w LEFT JOIN win_agcdr as r ON w.call_id = r.call_id and w.vcc_id=r.vcc_id '.
            'WHERE w.vcc_id=:vcc_id AND w.start_time >= :start_time '.$where.' lIMIT 3000',
            $par_arr
        );
        $data = $temp = array();
        if (!empty($result)) {
            foreach ($result as $v) {
                $temp['caller'] = $v['caller'];
                $temp['called'] = $v['called'];
                $temp['out'] = 'out';
                $temp['start_time'] = empty($v['start_time']) ? '' : date('Y-m-d H:i:s', $v['start_time']);
                $temp['conn_time'] =  empty($v['conn_time']) ? '' : date('Y-m-d H:i:s', $v['conn_time']);
                $temp['end_time'] = empty($v['end_time']) ? '' : date('Y-m-d H:i:s', $v['end_time']);
                $temp['all_secs'] = $v['all_sec'];
                //$temp['record_file'] = $v['record_file'];
                //接通才有录音；
                //$temp['record_file'] = $v['result'] == 0 ? $recordApiUrl.'/out/'.$vcc_id.'/'.$v['call_id'] : '';
                $temp['call_id'] = $v['call_id'];
                $temp['result'] = $v['result']==0 ? '接通' : '未接通';
                $data[] = $temp;
            }
        }
        $ret = array(
            'code' => 200,
            'message' => 'ok',
            'data' => $data,
        );
        return $ret;
    }

    /**
     * web呼叫；
     * @param array $param
     * @return array|string
     */
    public function ctiCallAction(array $param = array())
    {
        $vcc_code = empty($param['vcc_code']) ? 0 : $param['vcc_code'];
        $caller = empty($param['caller']) ? '' : $param['caller'];
        $called = empty($param['called']) ? '' : $param['called'];
        $timeout = empty($param['timeout']) ? '50' : $param['timeout'];
        $display_caller = empty($param['display_caller']) ? '' : $param['display_caller'];
        $display_called = empty($param['display_called']) ? '' : $param['display_called'];
        $if_transmit = empty($param['if_transmit']) ? '' : $param['if_transmit'];
        $is_showcaller = empty($param['is_showcaller']) ? '' : $param['is_showcaller'];
        $transfer_sound = empty($param['transfer_sound']) ? '' : $param['transfer_sound'];
        $transfer_sound = str_ireplace('.wav', '', $transfer_sound);
        $callTimeoutfile = empty($param['call_timeout_file']) ? '' : $param['call_timeout_file'];
        $callLimitTime = empty($param['call_limit_time']) ? '' : $param['call_limit_time'];
        $display_caller = $if_transmit == 1 ? $called : $display_caller;
        $display_called = $is_showcaller == 1 ? $caller : $display_called;
        //vcc_code 验证
        $msg = $vcc_id = $this->container->get('icsoc_data.validator')->checkVccCode($vcc_code);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }
        if (empty($caller)) {
            $ret = array(
                'code' => 403,
                'message' => '主叫号码为空',
            );
            return $ret;
        }
        if ($this->verifyPhoneIsValid($caller) === false) {
            $ret = array(
                'code' => 406,
                'message' => '主叫号码格式不正确',
            );
            return $ret;
        }
        if (empty($called)) {
            $ret = array(
                'code' => 404,
                'message' => '被叫号码为空',
            );
            return $ret;
        }
        if ($this->verifyPhoneIsValid($called) === false) {
            $ret = array(
                'code' => 407,
                'message' => '被叫号码格式不正确',
            );
            return $ret;
        }

        if (!empty($callLimitTime) && !is_numeric($callLimitTime)) {
            $ret = array(
                'code' => 408,
                'message' => 'call_limit_time非数字',
            );
            return $ret;
        }
        $numbers = $this->dbal->fetchAll(
            "SELECT phone,phone400 FROM cc_phone400s WHERE vcc_id = :vcc_id ",
            array('vcc_id'=>$vcc_id)
        );
        $vaildNum = array();
        foreach ($numbers as $num) {
            $vaildNum[] = $num['phone'];
            $vaildNum[] = $num['phone400'];
        }
        $vaildNum = array_unique($vaildNum);
        if ((!in_array($display_called, $vaildNum) && $is_showcaller != 1) ||
            (!in_array($display_caller, $vaildNum) && $if_transmit != 1)) {
            $ret = array(
                'code' => 408,
                'message' => '呼叫主叫号码显示或者呼叫被叫号码显示 不存在,请统一填写你们的400号码',
            );
            return $ret;
        }
        //发送socket数据
        //$user = $this->container->get("security.token_storage")->getToken()->getUser();
        $logger = $this->container->get('logger');
        $address = $this->container->get('icsoc_core.common.class')->newGetWinIp();
        //$address =$user->getWinIp();
        $port = $this->container->getParameter('win_socket_port');
        $caller = $this->checkPhoneArea($caller, $display_caller);
        $called = $this->checkPhoneArea($called, $display_called);
        $socket_command = "makecall($vcc_id,$display_caller,$caller,$timeout,0,1,callback_haodai,ivr_in,transoutpho=$called|transcaller=$display_called|transfer_sound=$transfer_sound|call_timeout_file=$callTimeoutfile|call_limit_time=$callLimitTime)";
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('无法创建socket：【'.$errorCode.'】'.$errorMsg);
            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        $res = socket_connect($socket, $address, $port);
        //连接失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('socket无法连接到【'.$address.':'.$port.'】：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        $socket_command .= "\r\n\r\n";
        $res = socket_write($socket, $socket_command, strlen($socket_command));

        //发送数据失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('socket发送数据失败：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        $responce = socket_read($socket, 1024);

        if ($responce === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('socket读取数据失败：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        //呼叫成功
        if (strstr($responce, 'Success')) {
            $responce = str_replace("\r\n", '', $responce);
            $logger->debug($responce);
            //呼叫成功返回 callid;
            $callid = trim(substr($responce, strpos($responce, 'CallID:')+7));
            $ret = array(
                'code' => 200,
                'message' => 'ok',
                'callid' => $callid,
            );

            return $ret;
        } else {
            $responce = str_replace("\r\n", '', $responce);
            $logger->debug($responce);
            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }
    }

    /**
     * web呼叫；
     * @param array $param
     * @return array|string
     */
    public function ctiCalltoQueAction(array $param = array())
    {
        $vcc_code = empty($param['vcc_code']) ? 0 : $param['vcc_code'];
        $caller = empty($param['caller']) ? '' : $param['caller'];
        $called = empty($param['called']) ? '' : $param['called'];
        $timeout = empty($param['timeout']) ? '50' : $param['timeout'];
        $queId = empty($param['que_id']) ? '0' : $param['que_id'];

        //vcc_code 验证
        $msg = $vcc_id = $this->container->get('icsoc_data.validator')->checkVccCode($vcc_code);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }
        if (empty($caller)) {
            $ret = array(
                'code' => 403,
                'message' => '主叫号码为空',
            );
            return $ret;
        }
        if ($this->verifyPhoneIsValid($caller) === false) {
            $ret = array(
                'code' => 406,
                'message' => '主叫号码格式不正确',
            );
            return $ret;
        }
        if (empty($called)) {
            $ret = array(
                'code' => 404,
                'message' => '被叫号码为空',
            );
            return $ret;
        }
        if ($this->verifyPhoneIsValid($called) === false) {
            $ret = array(
                'code' => 407,
                'message' => '被叫号码格式不正确',
            );
            return $ret;
        }

        //que 验证
        $msg = $this->container->get('icsoc_data.validator')->vccQue($vcc_id, $queId, 408);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }

        //发送socket数据
        //$user = $this->container->get("security.token_storage")->getToken()->getUser();
        $logger = $this->container->get('logger');
        $address = $this->container->get('icsoc_core.common.class')->newGetWinIp();
        //$address =$user->getWinIp();
        $port = $this->container->getParameter('win_socket_port');
        $caller = $this->checkPhoneArea($caller);
        $called = $this->checkPhoneArea($called);
        $socket_command = "makecall($vcc_id,$caller,$called,$timeout,0,1,ccod_mc,toque,transque=$queId)";
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('无法创建socket：【'.$errorCode.'】'.$errorMsg);
            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        $res = socket_connect($socket, $address, $port);
        //连接失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('socket无法连接到【'.$address.':'.$port.'】：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        $socket_command .= "\r\n\r\n";
        $res = socket_write($socket, $socket_command, strlen($socket_command));

        //发送数据失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('socket发送数据失败：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        $responce = socket_read($socket, 1024);

        if ($responce === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->debug('socket读取数据失败：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }

        //呼叫成功
        if (strstr($responce, 'Success')) {
            $responce = str_replace("\r\n", '', $responce);
            $logger->debug($responce);
            //呼叫成功返回 callid;
            $callid = trim(substr($responce, strpos($responce, 'CallID:')+7));
            $ret = array(
                'code' => 200,
                'message' => 'ok',
                'callid' => $callid,
            );

            return $ret;
        } else {
            $responce = str_replace("\r\n", '', $responce);
            $logger->debug($responce);
            $ret = array(
                'code' => 405,
                'message' => '呼叫失败',
            );
            return $ret;
        }
    }

    /**
     * 检查号码是否加0
     * @param $phone
     * @param $displayPhone
     * @return string
     */
    public function checkPhoneArea($phone, $displayPhone = '')
    {
        //车载设备号码
        if (strlen($phone) > 12) {
            return $phone;
        }
        if (!empty($displayPhone) && substr($displayPhone, 0, 1) == '0') {
            if (substr($displayPhone, 0, 3) == '010' || substr($displayPhone, 0, 2) == '02') {
                $line_code = substr($displayPhone, 0, 3);
            } else {
                //4位区号
                $line_code = substr($displayPhone, 0, 4);
            }
        } else {
            $line_code = $this->container->getParameter('local_code');
        }

        $res = $this->container->get("icsoc_data.model.location")->getNumberloc($phone);
        if ($res['code'] == 200 && $res['data']['type'] == 'MOBILE') {
            if (empty($res['data']['code'])) {
                return '0'.$res['data']['realPhone']; //没有找到
            } else {
                if ($line_code == $res['data']['code']) {
                    return $res['data']['realPhone'];
                } else {
                    return '0'.$res['data']['realPhone'];
                }
            }
        } elseif ($res['code'] == 200 && $res['data']['type'] == 'TEL') {
            if (empty($res['data']['code'])) {
                return $res['data']['realPhone']; //没有找到
            } else {
                if ($line_code == $res['data']['code']) {
                    return $res['data']['realPhone'];
                } else {
                    return $res['data']['code'].$res['data']['realPhone'];
                }
            }
        } else {
            return $phone;
        }
    }

    /**
     * 验证是否是正常的手机号码或固话
     *
     * @param string $phone
     * @return bool
     */
    public function verifyPhoneIsValid($phone)
    {
        $reg = '/^0?1[3-9]\d{9}$|^0\d{3}\d{8}$|^0\d{2}\d{8}$|^0\d{3}\d{7}|^400\d{7}|^106469\d{7}|^\d{8}$/';

        if (preg_match($reg, $phone)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param $vccCode
     * @param $callId
     * @return array
     */
    public function hangUp($vccCode, $callId)
    {
        $vccCode = empty($vccCode) ? 0 : $vccCode;
        $callId = empty($callId) ? '' : $callId;
        //vcc_code 验证
        $msg = $vcc_id = $this->container->get('icsoc_data.validator')->checkVccCode($vccCode);
        if (!empty($msg) && is_array($msg)) {
            return $msg;
        }
        if (empty($callId)) {
            $ret = array(
                'code' => 403,
                'message' => 'call_id为空',
            );
            return $ret;
        }
        //发送socket数据
        //$user = $this->container->get("security.token_storage")->getToken()->getUser();
        $logger = $this->container->get('logger');
        $address = $this->container->get('icsoc_core.common.class')->newGetWinIp();
        //$address =$user->getWinIp();
        $port = $this->container->getParameter('win_socket_port');
        $socketCommand = json_encode(['cli'=>'hangup','callid'=>$callId]);
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->error('无法创建socket：【'.$errorCode.'】'.$errorMsg);
            $ret = array(
                'code' => 405,
                'message' => '挂断失败',
            );
            return $ret;
        }

        $res = socket_connect($socket, $address, $port);
        //连接失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->error('socket无法连接到【'.$address.':'.$port.'】：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '挂断失败',
            );
            return $ret;
        }

        $socketCommand .= "\r\n\r\n";
        $res = socket_write($socket, $socketCommand, strlen($socketCommand));

        //发送数据失败
        if ($res === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->error('socket发送数据失败：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '挂断失败',
            );
            return $ret;
        }

        $responce = socket_read($socket, 1024);

        if ($responce === false) {
            $errorCode = socket_last_error();
            $errorMsg = socket_strerror($errorCode);
            $logger->error('socket读取数据失败：【'.$errorCode.'】'.$errorMsg);

            $ret = array(
                'code' => 405,
                'message' => '挂断失败',
            );
            return $ret;
        }

        //呼叫成功
        if (strstr($responce, 'Success')) {
            $responce = str_replace("\r\n", '', $responce);
            $logger->error($responce);
            $ret = array(
                'code' => 200,
                'message' => 'ok',
            );

            return $ret;
        } else {
            $responce = str_replace("\r\n", '', $responce);
            $logger->error($responce);
            $ret = array(
                'code' => 405,
                'message' => '挂断失败',
            );
            return $ret;
        }
    }
}
